<!DOCTYPE html>
<html>
<head>
<title>Test face framing support</title>
<link rel="help" href="https://w3c.github.io/mediacapture-extensions/">
</head>
<body>
<h1 class="instructions">Description</h1>
<p class="instructions">This test checks face framing support.</p>
<div id='log'></div>
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
"use strict";

const constraintSet = {
  faceFraming: true
};

Object.keys(constraintSet).forEach(property => {
  test(t => {
    const supportedConstraints =
        navigator.mediaDevices.getSupportedConstraints();
    assert_implements_optional(
        supportedConstraints[property],
        `Optional property ${property} not in supported constraints`);
  }, `Test getSupportedConstraints().${property}`);

  promise_test(async t => {
    const supportedConstraints =
        navigator.mediaDevices.getSupportedConstraints();

    const stream = await navigator.mediaDevices.getUserMedia({video: true});
    assert_equals(stream.getAudioTracks().length, 0);
    assert_equals(stream.getVideoTracks().length, 1);
    const [videoTrack] = stream.getVideoTracks();

    assert_equals(typeof videoTrack.getCapabilities, 'function');
    const capabilities = videoTrack.getCapabilities();
    assert_equals(typeof capabilities, 'object');

    if (!supportedConstraints[property]) {
      assert_false(property in capabilities);
    }

    assert_implements_optional(
        property in capabilities,
        `Optional property ${property} not in capabilities`);

    // Accept [false], [false, true], [true] and [true, false].
    assert_array_equals(
        capabilities[property],
        capabilities[property].length == 1
            ? [!!capabilities[property][0]]
            : [!!capabilities[property][0], !capabilities[property][0]]);
  }, `Test getCapabilities().${property}`);

  promise_test(async t => {
    const supportedConstraints =
        navigator.mediaDevices.getSupportedConstraints();

    const stream = await navigator.mediaDevices.getUserMedia({video: true});
    assert_equals(stream.getAudioTracks().length, 0);
    assert_equals(stream.getVideoTracks().length, 1);
    const [videoTrack] = stream.getVideoTracks();

    const capabilities = videoTrack.getCapabilities();

    assert_equals(typeof videoTrack.getSettings, 'function');
    const settings = videoTrack.getSettings();
    assert_equals(typeof settings, 'object');

    if (!supportedConstraints[property] || !(property in capabilities))
      assert_false(property in settings);

    assert_implements_optional(
        property in capabilities,
        `Optional property ${property} not in capabilities`);

    assert_in_array(settings[property], capabilities[property]);
  }, `Test getSettings().${property}`);

  promise_test(async t => {
    const supportedConstraints =
        navigator.mediaDevices.getSupportedConstraints();

    const stream = await navigator.mediaDevices.getUserMedia({video: true});
    assert_equals(stream.getAudioTracks().length, 0);
    assert_equals(stream.getVideoTracks().length, 1);
    const [videoTrack] = stream.getVideoTracks();

    const capabilities = videoTrack.getCapabilities();
    const constraints = {
      [property]: {exact: constraintSet[property]}
    };
    const oldSettings = videoTrack.getSettings();

    if (supportedConstraints[property] && !(property in capabilities)) {
      // The user agent supports |constraints| but |videoTrack| is not capable
      // to apply them.
      await videoTrack.applyConstraints(constraints).then(
        () => {
          assert_unreached('Unexpected success applying constraints');
        },
        error => {});
    } else {
      // The user agent does not support |constraints| and will ignore them or
      // the user agent supports |constraints| and |videoTrack| is capable to
      // apply them.
      await videoTrack.applyConstraints(constraints).then(
        () => {},
        error => {
          assert_unreached(`Error applying constraints: ${error.message}`);
        });
    }

    assert_equals(typeof videoTrack.getConstraints, 'function');
    const appliedConstraints = videoTrack.getConstraints();
    assert_equals(typeof appliedConstraints, 'object');
    const newSettings = videoTrack.getSettings();

    if (!supportedConstraints[property] || !(property in capabilities)) {
      // The user agent does not support |constraints| and ignored them or
      // the user agent supports |constraints| but |videoTrack| was not capable
      // to apply them.
      assert_object_equals(appliedConstraints, {});
    } else {
      // The user agent supports |constraints| and |videoTrack| was capable to
      // apply them.
      assert_object_equals(appliedConstraints, constraints);
    }

    if (!supportedConstraints[property] || !(property in capabilities) ||
        !capabilities[property].includes(constraintSet[property])) {
      // The user agent does not support |constraints| and ignored them or
      // the user agent supports |constraints| but |videoTrack| was not capable
      // to apply them or the user agent supports |constraints| and
      // |videoTrack| was capable to apply them but could not satisfy advanced
      // constraints and skipped them.
      assert_object_equals(newSettings, oldSettings);
    } else {
      // The user agent supports |constraints| and |videoTrack| was capable to
      // apply them and could satisfy advanced constraints.
      assert_equals(newSettings[property], constraintSet[property]);
    }
  }, `Test applyConstraints() with ${property}`);
});
</script>
</body>
</html>
